package com.dawn.module.hospital.service;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dawn.framework.common.pojo.CommonResult;
import com.dawn.framework.common.util.http.HttpUtils;
import com.dawn.framework.common.util.json.JsonUtils;
import com.dawn.framework.web.core.util.RequestUtils;
import com.dawn.framework.web.core.util.WebFrameworkUtils;
import com.dawn.module.hospital.controller.admin.refund.vo.RefundReqVO;
import com.dawn.module.hospital.controller.admin.refund.vo.SearchReqVO;
import com.dawn.module.hospital.dal.dataobject.msgsenduser.MsgSendUserDO;
import com.dawn.module.hospital.enums.BHConstants;
import com.dawn.module.hospital.enums.ErrorCodeConstants;
import com.dawn.module.hospital.enums.MsgSendTypeEnum;
import com.dawn.module.hospital.service.msgsenduser.MsgSendUserService;
import com.dawn.module.hospital.service.qrcodepay.QrcodePayService;
import com.dawn.module.hospital.util.RandomUtils;
import com.dawn.module.member.api.user.MemberUserApi;
import com.dawn.module.member.api.user.dto.MemberUserRespDTO;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.dawn.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
 * @description:
 * @author: cnsu-cmh
 * @time: 2024/8/19 10:19
 */
@Slf4j
@Service
public class RefundService extends BHService {


    @Resource
    private MemberUserApi memberUserApi;

    @Autowired
    private ChsOrderService chsOrderService;

    @Resource
    private QrcodePayService qrcodePayService;

    @Resource
    private RegisterService registerService;

    @Resource
    private OutpatientService outpatientService;

    @Autowired
    private InHospitalService inHospitalService;

    @Autowired
    private TemplateMsgService templateMsgService;

    @Resource
    private MsgSendUserService msgSendUserService;


    public CommonResult refundSys(String orderType,String refundReason,Map map) {

        String orderNumber = "";
        String business = "";
        String refundFee = "";
        if(BHConstants.ORDER_TYPE_REG.equals(orderType)){
            orderNumber = String.valueOf(map.get("registerNo"));
            refundFee = String.valueOf(map.get("amount"));
            business = "预约挂号";
        } else if (BHConstants.ORDER_TYPE_RECIPE.equals(orderType)) {
            orderNumber = String.valueOf(map.get("orderNumber"));
            refundFee = String.valueOf(map.get("fee"));
            business = "门诊缴费";
        } else if (BHConstants.ORDER_TYPE_PRE_PAYMENT.equals(orderType)) {
            orderNumber = String.valueOf(map.get("orderNumber"));
            refundFee = String.valueOf(map.get("payAmount"));
            business = "住院预交";
        }

        String payScene = String.valueOf(map.get("payScene"));
        String payWay = BHConstants.ALIPAY_MINI_APPLET.equals(payScene) ? CDBPayUtils.ALI : CDBPayUtils.WX;

        CommonResult refundResult = CommonResult.error(ErrorCodeConstants.BH_ERROR.getCode(),"退款操作失败");
        String refundNo = "TF" + RandomUtils.buildRandomStr(4);
        int amount = new BigDecimal(refundFee).multiply(new BigDecimal(100)).intValue();
        if(amount>0){
            refundResult = CDBPayUtils.instance().build(payWay)
                    .refundOrder(orderNumber,refundNo,refundFee, refundReason);
        }else {
            refundResult = CommonResult.success(new HashMap<String, String>(){{put("REFUNDNO",refundNo);}});
        }

        Map refundMap = new HashMap();
        refundMap.put("patientName",String.valueOf(map.get("patientName")));
        refundMap.put("clinicNo",String.valueOf(map.get("clinicNo")));
        refundMap.put("openid",String.valueOf(map.get("userId")));
        refundMap.put("des",refundReason);
        refundMap.put("business",business);
        refundMap.put("orderNo",orderNumber);
        refundMap.put("seqNo",String.valueOf(map.get("registerNo")));
        refundMap.put("totalCost",refundFee);
        refundMap.put("operType","REFUND");
        refundMap.put("status",0);
        refundMap.put("refundNo",refundNo);

        saveRefundOrder(refundMap,orderType,orderNumber);

        return refundResult;
    }

    public void saveRefundOrder(Map refundMap, String orderType, String orderNumber) {
        CommonResult saveResult = HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_SAVE_REFUND.getValue(), refundMap);
        if(saveResult.isError()) {
            log.error("-------退号退款订单保存失败 refundMap-----"+ JsonUtils.toJsonString(refundMap));
            log.error("-------退号退款订单保存失败 Message-----"+saveResult.getMsg());
        }

        if (BHConstants.ORDER_TYPE_REG.equalsIgnoreCase(orderType)) {
            // 修改挂号单状态
            HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_UPDATE_REG_PROCEDURE_STATUS.getValue(),
                    ImmutableMap.of("procedureStatus","REFUND","orderNumber",orderNumber));
        }
        if (BHConstants.ORDER_TYPE_RECIPE.equalsIgnoreCase(orderType)) {
            // 修改门诊缴费单状态
            HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_UPDATE_OUTPATIENT_PROCEDURE_STATUS.getValue(),
                    ImmutableMap.of("procedureStatus","REFUND","orderNumber",orderNumber));
        }
//        if (BHConstants.ORDER_TYPE_PRE_PAYMENT.equalsIgnoreCase(orderType)) {
//            // 修改住院预交单状态
//            HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_UPDATE_INHOSPITAL_PROCEDURE_STATUS.getValue(),
//                    ImmutableMap.of("procedureStatus","REFUND","orderNumber",orderNumber));
//        }

        if (orderNumber.indexOf("QAC") != -1) {
            Map qrcodeRefundMap = new HashMap<>();
            String refundNo = String.valueOf(refundMap.get("refundNo"));
            String refundAmount = String.valueOf(refundMap.get("totalCost"));
            String refundReason = String.valueOf(refundMap.get("des"));
            qrcodeRefundMap.put("orderNumber",orderNumber);
            qrcodeRefundMap.put("refundNo",refundNo);
            qrcodeRefundMap.put("refundAmount",refundAmount);
            qrcodeRefundMap.put("refundReason",refundReason);
            qrcodePayService.payRefund(qrcodeRefundMap);
        }
    }

    public void saveRefundExamine(String orderType,Map map,String errMsg) {
        Map examineMap = new HashMap();
        examineMap.put("status",0);
        examineMap.put("des",errMsg);
        examineMap.put("patientId",String.valueOf(map.get("patientId")));
        examineMap.put("patientName",String.valueOf(map.get("patientName")));
        examineMap.put("userId",String.valueOf(map.get("userId")));
        examineMap.put("payScene",String.valueOf(map.get("payScene")));
        examineMap.put("payType",String.valueOf(map.get("payModeName")));
        if(BHConstants.ORDER_TYPE_REG.equals(orderType)){
//            refundSys(orderType,BHConstants.WEIXIN_SERVICE_ACCOUNTS.getMsg() + "挂号失败退费",map);
            examineMap.put("orderNo",String.valueOf(map.get("registerNo")));
            examineMap.put("totalCost",String.valueOf(map.get("amount")));
            examineMap.put("business","预约挂号");
        } else if (BHConstants.ORDER_TYPE_RECIPE.equals(orderType)) {
            examineMap.put("orderNo",String.valueOf(map.get("orderNumber")));
            examineMap.put("totalCost",String.valueOf(map.get("fee")));
            examineMap.put("business","门诊缴费");
        } else if (BHConstants.ORDER_TYPE_PRE_PAYMENT.equals(orderType)) {
            examineMap.put("orderNo",String.valueOf(map.get("orderNumber")));
            examineMap.put("totalCost",String.valueOf(map.get("payAmount")));
            examineMap.put("business","住院预交");
        }

        CommonResult examineResult = HttpUtils.getHttp(getHisServerUri() + BHConstants.HIS_SAVE_REFUND_EXAMINE.getValue(), examineMap);
        if (examineResult.isSuccess()) {
            // TODO 退费
//                OrderRefundExamine examine = JSON.toJavaObject((JSONObject)examineResult.getData(), OrderRefundExamine.class);
            JSONObject jsonObject = (JSONObject) examineResult.getData();
            templateMsgService.sendRefundExamine(jsonObject);
        }
        // TODO 推送退费消息
        templateMsgService.sendMsgRefund(orderType,map);

    }

    public CommonResult isHaveExamine(Long userId) {
        if(StringUtils.isEmpty(userId)) {
            return CommonResult.error(ERROR_CODE,"请传入userId");
        }
        log.warn("退费审核消息的操作用户 userId:"+userId);

        List<MsgSendUserDO> msgSendUserDOList = msgSendUserService.getListByType(MsgSendTypeEnum.V_REFUND_EXAMINE.getCode());
        log.info("*********** 退费审核消息通知用户 ***********msgSendUserDOList:"+JsonUtils.toJsonString(msgSendUserDOList));
        if(msgSendUserDOList.size() == 0){
            return CommonResult.error(ErrorCodeConstants.BH_ERROR.getCode(),"消息推送用户无数据");
        }

        MemberUserRespDTO wxUser = memberUserApi.getUser(userId);
        log.warn("退费审核消息的操作用户 wxUser:"+JsonUtils.toJsonString(wxUser));

        boolean isExamine = false;
        for (MsgSendUserDO msgSendUserDO : msgSendUserDOList) {
            if(wxUser.getOpenid().equals(msgSendUserDO.getOpenid())){
                isExamine = true;
                break;
            }
        }

        if(!isExamine){
            return CommonResult.error(ERROR_CODE,"该用户暂无审核权限");
        }
        return CommonResult.success(true);
    }

    public CommonResult getExamineDetail(Long examineId) {
        if(StringUtils.isEmpty(examineId)) {
            return CommonResult.error(ERROR_CODE,"请传入审核单据ID-examineId");
        }

        CommonResult findResult = HttpUtils.getHttp(getHisServerUri() + BHConstants.HIS_GET_REFUND_EXAMINE.getValue(), ImmutableMap.of("id", examineId));
        if(findResult.isError()) {
            return findResult;
        }

        HashMap map = new HashMap();
        JSONObject examine = (JSONObject)findResult.getData();
        map.put("examine",examine);

        CommonResult payResult =  CDBPayUtils.instance().build(CDBPayUtils.WX).query(examine.getString("orderNo"));
        log.warn("-------订单查询 payQueryResult-----json:"+ JsonUtils.toJsonString(payResult));
        if(payResult.isSuccess()) {
            JSONObject res = (JSONObject)payResult.getData();
            map.put("payOrder",res);
        }else {
            payResult = CDBPayUtils.instance().build(CDBPayUtils.WX_CHS).chsQuery(examine.getString("orderNo"));
            log.info("-------订单查询 WX_CHS payQueryResult-----json:"+ JsonUtils.toJsonString(payResult));
            if(payResult.isSuccess()) {
                JSONObject res = (JSONObject)payResult.getData();
                JSONObject payOrder = res.getJSONObject("payOrder");
                JSONObject chsOrder = res.getJSONObject("chsOrder");
                map.put("payOrder",payOrder);
                map.put("chsOrder",chsOrder);
            }
        }
        return CommonResult.success(map);
    }

    public CommonResult examine(Long examineId,Long userId) {
        if(StringUtils.isEmpty(examineId)) {
            return CommonResult.error(ERROR_CODE,"请传入审核单据ID-examineId");
        }
        if(StringUtils.isEmpty(userId)) {
            return CommonResult.error(ERROR_CODE,"请传入userId");
        }

        CommonResult findResult = HttpUtils.getHttp(getHisServerUri() + BHConstants.HIS_GET_REFUND_EXAMINE.getValue(), ImmutableMap.of("id", examineId));
        if(findResult.isError()) {
            return findResult;
        }

        JSONObject examine = (JSONObject)findResult.getData();
        String orderNumber = examine.getString("orderNo");
        if(examine.getInteger("status").intValue() > 0) {
            String message = "订单号:" + orderNumber + "由操作员" + examine.getString("operatorId") + "已受理，无需重复受理";
            return CommonResult.error(ERROR_CODE,message);
        }

        String cancelSerialNo = RandomUtils.buildRandomStr(4);
        String refundNo = "TF" + cancelSerialNo;

        String payType = examine.getString("payType");
        String payScene = examine.getString("payScene");
        CommonResult refundResult = CommonResult.error(ERROR_CODE, "退费失败");
        if(BHConstants.PAY_CARD_WX_CHS_HIS.equals(payType)){

            // 微信医保移动支付
            log.info("-------医保移动支付-审核退款-支付订单查询 orderNumber:"+orderNumber);
            CommonResult queryResult = CDBPayUtils.instance()
                    .build(CDBPayUtils.WX_CHS)
                    .chsQuery(orderNumber);

            log.info("-------医保移动支付-审核退款-支付订单查询 payQueryResult-----json:"+JSON.toJSONString(queryResult));

            if (queryResult.isSuccess()) {
                JSONObject res = (JSONObject)queryResult.getData();
                JSONObject payOrder = res.getJSONObject("payOrder");
                JSONObject chsOrder = res.getJSONObject("chsOrder");
                int refundState = payOrder.getInteger("refundState");
                if (refundState == 2) {
                    // 已退款
                    CommonResult rqResult = CDBPayUtils.instance()
                            .build(CDBPayUtils.WX_CHS)
                            .refundQuery(payOrder.getString("payOrderId"));

                    if (rqResult.isSuccess()) {
                        JSONArray refundArray = (JSONArray) rqResult.getData();
                        JSONObject refundObject = refundArray.getJSONObject(0);
                        refundNo = refundObject.getString("mchRefundNo");
                        refundResult = CommonResult.success(refundNo);
                    }
                } else {
                    String patientId = "";
                    int sfgh = 0;
                    if (orderNumber.indexOf("GH") != -1) {
                        sfgh = 1;
                    } else if (orderNumber.indexOf("JF") != -1 || orderNumber.indexOf("QR") != -1
                            || orderNumber.indexOf("NAT") != -1 || orderNumber.indexOf("HIV") != -1 ) {
                        sfgh = 0;
                        // 缴费
                        CommonResult findBillResult = HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_GET_OUTPATIENT_BILL_ORDER.getValue(), ImmutableMap.of("orderNumber", orderNumber));
                        if (findBillResult.isSuccess()) {
                            Map billMap = (Map) findBillResult.getData();
                            patientId = (String) billMap.get("patientId");
                        }
                    }
                    Long totalFee = chsOrder.getLong("totalFee");
                    BigDecimal totalFeeYuan = new BigDecimal(totalFee).divide(new BigDecimal(100));
                    String totalCost = totalFeeYuan.setScale(2, BigDecimal.ROUND_HALF_UP).toString();

                    Long cashFee = chsOrder.getLong("cashFee");
                    BigDecimal cashFeeYuan = new BigDecimal(cashFee).divide(new BigDecimal(100));
                    String cashCost = cashFeeYuan.setScale(2, BigDecimal.ROUND_HALF_UP).toString();


                    String refundReason = "同步HIS失败，患者要求退费";

                    JSONObject hisRefundRsp = chsOrderService.chsPayRefundHis(patientId, sfgh, totalCost, orderNumber,refundReason,chsOrder);
                    if(!"1".equals(hisRefundRsp.getString("code"))) {
                        String errMsg = hisRefundRsp.getString("msg");
                        refundResult = CommonResult.error(ERROR_CODE, "HIS冲销失败:" + errMsg);
                    } else {
                        HashMap<String, Object> chsParams = new HashMap();
                        /*撤销流水号*/
                        chsParams.put("cancelSerialNo",cancelSerialNo);
                        /*撤销单据号*/
                        chsParams.put("cancelBillNo",chsOrder.getString("serialNo"));
                        /**
                         * 部分退款
                         * 非必填,不填则整单退款，CASH_ONLY则只退现金部分,
                         * 现金跟医保可以分开退款，医保部分调中台【6203】接口退款。
                         * */
                        chsParams.put("partRefundType","CASH_ONLY");
                        /**
                         * 现金部分退款
                         *
                         * 不填默认全退，填写时则退指定金额，不能为0，
                         * 仅当part_refund_type为空或CASH_ONLY时生效
                         *
                         * */
                        chsParams.put("cashRefundFee",cashCost);

                        /**
                         * 个账部分退款
                         * 新版接口已删除 医保部分调中台【6203】接口退款。
                         */
                        //                chsParams.put("insRefundFee","");

                        /**
                         * {”payOrdId” :”******”,”ref_reason”:”******”}
                         * ref_reason退款原因
                         * payOrdId: 对应处方上传的出参单号
                         */
//                    String refundReason = "同步HIS失败，患者要求退费";
                        JSONObject requestContentJson = new JSONObject();
                        requestContentJson.put("payOrdId", chsOrder.getString("payOrdId"));
                        requestContentJson.put("ref_reason", refundReason);
                        String requestContent = requestContentJson.toJSONString();
                        chsParams.put("requestContent", requestContent);

                        log.info("-------发送退款请求-----");

                        refundResult = CDBPayUtils.instance()
                                .build(CDBPayUtils.WX_CHS)
                                .chsRefundOrder(orderNumber, refundNo, totalCost, "审核退款请求退款", chsParams);
                    }
                }
            } else {
                refundResult = queryResult;
            }
        } else if (BHConstants.PAY_CARD_ALI_CHS_HIS.equals(payType)) {
            //支付宝医保移动支付

        } else {
            String payWay = BHConstants.ALIPAY_MINI_APPLET.getMsg().equals(payScene) ? CDBPayUtils.ALI : CDBPayUtils.WX;
            refundResult = CDBPayUtils.instance().build(payWay)
                    .refundOrder(orderNumber,refundNo,examine.getString("totalCost"),"审核退款请求退款");
        }

        log.info("-------审核退款请求退款结果-----"+JSON.toJSONString(refundResult));
        if (refundResult.isError()) {
            return refundResult;
        }

        Map<String,Object> refundMap = new HashMap();
        refundMap.put("orderNo",orderNumber);
        refundMap.put("refundNo",refundNo);
        refundMap.put("totalCost",examine.getString("totalCost"));
        refundMap.put("patientName",examine.getString("patientName"));
        refundMap.put("clinicNo",examine.getString("patientId"));
        refundMap.put("openid",examine.getString("userId"));
        refundMap.put("des",examine.getString("des"));
        refundMap.put("business",examine.getString("business"));
        refundMap.put("seqNo","REFUND");
        if("退号".equals(examine.getString("business")) || "核酸取消预约".equals(examine.getString("business"))) {
            refundMap.put("operType","REFUND");
        } else {
            refundMap.put("operType","ABNORMAL_REFUND");
        }

        refundMap.put("payType",examine.getString("payType"));
        refundMap.put("status",0);

//        HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_SAVE_REFUND.getValue(), refundMap);

        MemberUserRespDTO wxUser = memberUserApi.getUser(userId);

        Map examineMap = new HashMap();
        examineMap.put("orderNo",orderNumber);
        examineMap.put("operatorId",wxUser.getNickname()+"<br/>"+wxUser.getOpenid());
        examineMap.put("totalCost",examine.getString("totalCost"));
        examineMap.put("status","1");
        CommonResult saveResult = HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_SAVE_REFUND_EXAMINE.getValue(), examineMap);
        if(saveResult.isError()) {
            log.error("-------退号退款订单保存失败 refundMap-----"+ JsonUtils.toJsonString(refundMap));
            log.error("-------退号退款订单保存失败 Message-----"+saveResult.getMsg());
        }


        String orderType = "";
        if (orderNumber.indexOf("GH") != -1 || orderNumber.indexOf("ZJGH") != -1) {
            orderType = BHConstants.ORDER_TYPE_REG;
        }
        if (orderNumber.indexOf("JF") != -1 || orderNumber.indexOf("QR") != -1
                || orderNumber.indexOf("NAT") != -1 || orderNumber.indexOf("HIV") != -1 ) {
            orderType = BHConstants.ORDER_TYPE_RECIPE;
        }
        if (orderNumber.indexOf("ZYYJ") != -1) {
            orderType = BHConstants.ORDER_TYPE_PRE_PAYMENT;
        }

        saveRefundOrder(refundMap,orderType,orderNumber);

        return CommonResult.success("订单号: "+ orderNumber+ "退款成功，请患者注意查收");
    }

    public List<HashMap<String, String>> getAbnormalOrderList(SearchReqVO reqVO) {
        Map<String, Object> requestBody = new HashMap<>();

        if (reqVO.getSearchTime() != null && reqVO.getSearchTime().length > 1) {
            LocalDateTime beginDateTime = reqVO.getSearchTime()[0];
            LocalDateTime endDateTime = reqVO.getSearchTime()[1];
            requestBody.put("beginDate",LocalDateTimeUtil.formatNormal(beginDateTime));
            requestBody.put("endDate",LocalDateTimeUtil.formatNormal(endDateTime));
        }

        if (StringUtils.hasText(reqVO.getPatientName())) {
            requestBody.put("patientName",reqVO.getPatientName());
        }
        if (StringUtils.hasText(reqVO.getPatientId())) {
            requestBody.put("patientId",reqVO.getPatientId());
        }
        if (StringUtils.hasText(reqVO.getOrderNo())) {
            requestBody.put("orderNo",reqVO.getOrderNo());
        }

        List<HashMap<String,String>> orderNoList = new ArrayList<>();
        if (BHConstants.ORDER_TYPE_REG.equalsIgnoreCase(reqVO.getOrderType())) {
            // 挂号列表
            if (StringUtils.hasText(reqVO.getClinicNo())) {
                requestBody.put("clinicNo",reqVO.getClinicNo());
            }
            CommonResult httpResult = HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_GET_REGISTER_ABNORMAL_LIST.getValue(),requestBody);
            if(httpResult.isSuccess()) {
                JSONArray data = (JSONArray)httpResult.getData();
                data.stream().forEach(d -> {
                    JSONObject order = (JSONObject)d;
                    HashMap hashMap = new HashMap();
                    hashMap.put("orderType","挂号");
                    hashMap.put("patientName",order.getString("patientName"));
                    hashMap.put("patientId",order.getString("patientId"));
                    hashMap.put("clinicNo",order.getString("clinicNo"));
                    hashMap.put("orderNo",order.getString("registerNo"));
                    hashMap.put("orderId",order.getString("thirdOrderNo"));
                    hashMap.put("cost",order.getString("totalCost"));

                    DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    String createTime =  ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(order.getLong("createTime")), ZoneId.systemDefault()));
                    hashMap.put("createTime",createTime);
                    hashMap.put("payTime",order.getString("payTime"));

                    if ("fails".equalsIgnoreCase(order.getString("procedureStatus"))) {
                        hashMap.put("payStatus","挂号失败");
                    }else if ("refund".equalsIgnoreCase(order.getString("procedureStatus"))) {
                        hashMap.put("payStatus","已退号");
                    } else {
                        hashMap.put("payStatus","未知");
                    }

                    hashMap.put("refundStatus","unrefund");
                    CommonResult refundResult = HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_GET_REFUND_INFO.getValue(), ImmutableMap.of("orderNo",order.getString("registerNo")));
                    if (refundResult.isSuccess()) {
                        List<Map> refundMapList = (List<Map>) refundResult.getData();
                        if(refundMapList!=null){
                            for (Map m : refundMapList) {
                                String status = String.valueOf(m.get("status"));
                                if("0".equals(status)){
                                    hashMap.put("refundStatus","refund");
                                    break;
                                }
                            }
                        }
                    }

                    orderNoList.add(hashMap);
                });
            }

        } else if (BHConstants.ORDER_TYPE_RECIPE.equalsIgnoreCase(reqVO.getOrderType())) {
            // 缴费列表
            if (StringUtils.hasText(reqVO.getClinicNo())) {
                requestBody.put("clinicNo",reqVO.getClinicNo());
            }

            CommonResult httpResult = HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_GET_BILL_ABNORMAL_LIST.getValue(),requestBody);
            if(httpResult.isSuccess()) {
                JSONArray data = (JSONArray)httpResult.getData();
                data.stream().forEach(d -> {
                    JSONObject order = (JSONObject)d;
                    HashMap hashMap = new HashMap();
                    hashMap.put("orderType","门诊缴费");
                    hashMap.put("patientName",order.getString("patientName"));
                    hashMap.put("patientId",order.getString("patientId"));
                    hashMap.put("clinicNo",order.getString("clinicNo"));
                    hashMap.put("orderNo",order.getString("orderNumber"));
                    hashMap.put("orderId",order.getString("thirdOrderNo"));
                    hashMap.put("cost",order.getString("fee"));

                    DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    String createTime =  ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(order.getLong("createTime")), ZoneId.systemDefault()));
                    hashMap.put("createTime",createTime);

                    hashMap.put("payTime",order.getString("payTime"));

                    if ("fails".equalsIgnoreCase(order.getString("procedureStatus"))) {
                        hashMap.put("payStatus","缴费失败");
                    }else if ("refund".equalsIgnoreCase(order.getString("procedureStatus"))) {
                        hashMap.put("payStatus","已退款");
                    } else {
                        hashMap.put("payStatus","未知");
                    }

                    hashMap.put("refundStatus","unrefund");
                    CommonResult refundResult = HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_GET_REFUND_INFO.getValue(), ImmutableMap.of("orderNo",order.getString("orderNumber")));
                    if (refundResult.isSuccess()) {
                        List<Map> refundMapList = (List<Map>) refundResult.getData();
                        if(refundMapList!=null){
                            for (Map m : refundMapList) {
                                String status = String.valueOf(m.get("status"));
                                if("0".equals(status)){
                                    hashMap.put("refundStatus","refund");
                                    break;
                                }
                            }
                        }
                    }

                    orderNoList.add(hashMap);
                });

            }
        } else if (BHConstants.ORDER_TYPE_PRE_PAYMENT.equalsIgnoreCase(reqVO.getOrderType())) {
            // 住院预交列表
            if (StringUtils.hasText(reqVO.getClinicNo())) {
                requestBody.put("inPatientNo",reqVO.getClinicNo());
            }
        }


        return orderNoList;
    }

    public CommonResult abnormalRefund(RefundReqVO reqVO) {
        String orderType = reqVO.getOrderType();
        String orderNumber = reqVO.getOrderNo();
        String payWay;
        String patientId = "";
        Map refundMap = new HashMap();
        if("QAC".equals(orderType)) {
            // 扫码盒子异常退费
            payWay = CDBPayUtils.WX;
        } else {
            CommonResult result = CommonResult.error(ErrorCodeConstants.PAY_ERROR.getCode(),"订单类型"+orderType+"传入错误");

            if (BHConstants.ORDER_TYPE_REG.equalsIgnoreCase(reqVO.getOrderType())) {
                // 挂号
                result = registerService.queryByOrderNumber(orderNumber);
            } else if (BHConstants.ORDER_TYPE_RECIPE.equalsIgnoreCase(reqVO.getOrderType())) {
                // 门诊缴费
                result = outpatientService.queryBillByOrderNumber(orderNumber);
            }else if (BHConstants.ORDER_TYPE_PRE_PAYMENT.equalsIgnoreCase(reqVO.getOrderType())) {
                // 住院预交
                result = inHospitalService.queryByOrderNumber(orderNumber);
            }
            if (result.isError()) {
                return result;
            }

            Map findResultMap = (Map) result.getData();
            patientId = (String) findResultMap.get("patientId");
            String openid = (String) findResultMap.get("userId");
            String patientName = String.valueOf(findResultMap.get("patientName"));

            String payStatus = (String) findResultMap.get("payStatus");
            String procedureStatus = String.valueOf(findResultMap.get("procedureStatus"));
            String payScene = (String) findResultMap.get("payScene");

            if("payoff".equals(payStatus) && procedureStatus.equals("success") ){
                return CommonResult.error(ErrorCodeConstants.PAY_ERROR.getCode(),"订单号"+ orderNumber +"不属于异常状态,暂不支持异常退款操作");
            } else {
                if(payScene.equals(BHConstants.ALIPAY_MINI_APPLET.getMsg())){
                    //支付宝小程序
                    payWay = CDBPayUtils.ALI;
                }else {
                    String payModeName = (String)findResultMap.get("payModeName");
                    if(payModeName.equals(BHConstants.PAY_CARD_WX_CHS_HIS)){
                        // 医保移动支付-微信
                        payWay = CDBPayUtils.WX_CHS;
                    } else {
                        // 银医-中国农业银行
                        payWay = CDBPayUtils.WX;
                    }
                }
                refundMap.put("patientName",patientName);
                refundMap.put("clinicNo",findResultMap.get("patientId"));
                refundMap.put("openid",openid);
            }
        }


        String cancelSerialNo = RandomUtils.buildRandomStr(4);
        String refundNo = "TF" + cancelSerialNo;

        CommonResult refundResult = CommonResult.error(ERROR_CODE, "退费失败");

        if(CDBPayUtils.WX_CHS.equals(payWay)) {
            // 微信医保移动支付
            log.info("-------医保移动支付-退款-支付订单查询 orderNumber:"+orderNumber);
            CommonResult queryResult = CDBPayUtils.instance().build(CDBPayUtils.WX_CHS).chsQuery(reqVO.getOrderNo());
            log.info("-------医保移动支付-退款-支付订单查询 payQueryResult-----json:"+ JsonUtils.toJsonString(queryResult));
            if(queryResult.isError()){
                return CommonResult.error(ErrorCodeConstants.PAY_ERROR.getCode(),"退款失败,支付订单数据不存在");
            }

            JSONObject res = (JSONObject)queryResult.getData();
            JSONObject payOrder = res.getJSONObject("payOrder");
            JSONObject chsOrder = res.getJSONObject("chsOrder");
            int refundState = payOrder.getInteger("refundState");
            if(refundState == 2) {
                // 已退款
                CommonResult rqResult = CDBPayUtils.instance().build(CDBPayUtils.WX_CHS).refundQuery(payOrder.getString("payOrderId"));
                log.info("-------医保移动支付-退款-支付订单查询 rqResult-----json:"+ JsonUtils.toJsonString(rqResult));

                if (rqResult.isSuccess()) {
                    JSONArray refundArray = (JSONArray) rqResult.getData();
                    JSONObject refundObject = refundArray.getJSONObject(0);
                    Map re = new HashMap();
                    re.put("REFUNDNO",refundObject.getString("mchRefundNo"));
                    return CommonResult.success(re);
                }
            } else {
                int sfgh = 0;
                if (orderNumber.indexOf("GH") != -1) {
                    sfgh = 1;
                } else if (orderNumber.indexOf("JF") != -1 || orderNumber.indexOf("QR") != -1
                        || orderNumber.indexOf("NAT") != -1 || orderNumber.indexOf("HIV") != -1) {
                    sfgh = 0;
                }
                Long totalFee = chsOrder.getLong("totalFee");
                BigDecimal totalFeeYuan = new BigDecimal(totalFee).divide(new BigDecimal(100));
                String totalCost = totalFeeYuan.setScale(2, BigDecimal.ROUND_HALF_UP).toString();

                Long cashFee = chsOrder.getLong("cashFee");
                BigDecimal cashFeeYuan = new BigDecimal(cashFee).divide(new BigDecimal(100));
                String cashCost = cashFeeYuan.setScale(2, BigDecimal.ROUND_HALF_UP).toString();


                String refundReason = "同步HIS失败，患者要求退费";

                JSONObject hisRefundRsp = chsOrderService.chsPayRefundHis(patientId, sfgh, totalCost, orderNumber,refundReason,chsOrder);
                if(!"1".equals(hisRefundRsp.getString("code"))) {
                    String errMsg = hisRefundRsp.getString("msg");
                    refundResult = CommonResult.error(ERROR_CODE, "HIS冲销失败:" + errMsg);
                } else {
                    HashMap<String, Object> chsParams = new HashMap();
                    /*撤销流水号*/
                    chsParams.put("cancelSerialNo",cancelSerialNo);
                    /*撤销单据号*/
                    chsParams.put("cancelBillNo",chsOrder.getString("serialNo"));
                    /**
                     * 部分退款
                     * 非必填,不填则整单退款，CASH_ONLY则只退现金部分,
                     * 现金跟医保可以分开退款，医保部分调中台【6203】接口退款。
                     * */
                    chsParams.put("partRefundType","CASH_ONLY");
                    /**
                     * 现金部分退款
                     *
                     * 不填默认全退，填写时则退指定金额，不能为0，
                     * 仅当part_refund_type为空或CASH_ONLY时生效
                     *
                     * */
                    chsParams.put("cashRefundFee",cashCost);

                    /**
                     * 个账部分退款
                     * 新版接口已删除 医保部分调中台【6203】接口退款。
                     */
                    //                chsParams.put("insRefundFee","");

                    /**
                     * {”payOrdId” :”******”,”ref_reason”:”******”}
                     * ref_reason退款原因
                     * payOrdId: 对应处方上传的出参单号
                     */
//                    String refundReason = "同步HIS失败，患者要求退费";
                    JSONObject requestContentJson = new JSONObject();
                    requestContentJson.put("payOrdId", chsOrder.getString("payOrdId"));
                    requestContentJson.put("ref_reason", refundReason);
                    String requestContent = requestContentJson.toJSONString();
                    chsParams.put("requestContent", requestContent);

                    log.info("-------发送退款请求-----");

                    refundResult = CDBPayUtils.instance()
                            .build(CDBPayUtils.WX_CHS)
                            .chsRefundOrder(orderNumber, refundNo, totalCost, "审核退款请求退款", chsParams);
                }
            }

        } else {
            HttpServletRequest request = WebFrameworkUtils.getRequest();
            String spbillCreateIp = RequestUtils.getClientIp(request);
            refundResult = CDBPayUtils.instance().build(payWay)
                    .refundOrder(orderNumber, refundNo, reqVO.getRefundFee(), "管理平台异常退费,电脑IP:" + spbillCreateIp);

        }

        log.info("-------异常退费请求退款结果-----"+JSON.toJSONString(refundResult));
        if (refundResult.isError()) {
            return refundResult;
        }


//        Map<String,Object> refundMap = new HashMap();
        refundMap.put("orderNo",orderNumber);
        refundMap.put("refundNo",refundNo);
        refundMap.put("totalCost",reqVO.getRefundFee());
        refundMap.put("des","异常退费");
        refundMap.put("business",orderType);
        refundMap.put("operType","ABNORMAL_REFUND");
        refundMap.put("payType",payWay);
        refundMap.put("status",0);

        saveRefundOrder(refundMap,reqVO.getOrderType(),orderNumber);
//        CommonResult saveResult = HttpUtils.postForm(getHisServerUri() + BHConstants.HIS_SAVE_REFUND.getValue(), refundMap);
//        if(saveResult.isError()) {
//            log.error("-------退号退款订单保存失败 refundMap-----"+ JsonUtils.toJsonString(refundMap));
//            log.error("-------退号退款订单保存失败 Message-----"+saveResult.getMsg());
//        }

        return CommonResult.success("订单号: "+ orderNumber+ "退款成功，请患者注意查收");
    }

    public List<Map<String, String>> getQacAbnormalOrderList(String orderNo) {
        List<Map<String,String>> orderList = new ArrayList<>();
        CommonResult queryResult = CDBPayUtils.instance().queryOrderInfo(orderNo);
        if(queryResult.isSuccess()) {
            Map res = (Map)queryResult.getData();
            String trade_item = (String)res.get("body");
            Map m = JSON.parseObject(trade_item,Map.class);
            res.putAll(m);
            orderList.add(res);
        }
        return orderList;
    }
}
